using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using MvcWiki.Service;
using MvcWiki.ViewModel;

namespace MvcWiki.Web.Prototype.MVC2P1.Wiki.Controllers
{
    [HandleError]
    public class WikiPageController : Controller
    {
        IWikiNamespaceService WikiNamespaceService;
        IWikiPageService WikiPageService;

        public WikiPageController(IWikiNamespaceService wikiNamespaceService, IWikiPageService wikiPageService)
        {
            this.WikiNamespaceService = wikiNamespaceService;
            this.WikiPageService = wikiPageService;
        }

        public ActionResult Index(string @namespace)
        {
            var wikiPages = WikiPageService.GetAllWikiPages(@namespace);

            var wikiNamespaceViewModel = new WikiNamespaceViewModel
            {
                Name = @namespace,
                Pages = wikiPages.Select(
                    x => new WikiPageViewModel { Name = x.Name, Namespace = @namespace }
                ).ToList()
            };

            return View(wikiNamespaceViewModel);
        }

        public ActionResult Show(string @namespace, string page, string revision)
        {
            var wikiPageViewModel = new MvcWiki.ViewModel.WikiPageViewModel
            {
                Namespace = @namespace,
                Name = page
            };

            try
            {
                var wikiPage = WikiPageService.GetWikiPage(@namespace, page);

                if (wikiPage.Revisions.Count > 0)
                {
                    wikiPageViewModel.HasContent = true;

                    var revisions = wikiPage.Revisions.OrderByDescending(x => x.Created).ToList();

                    if (String.IsNullOrEmpty(revision))
                    {
                        wikiPageViewModel.Revision = revisions.First().Created.ToString("u");
                        wikiPageViewModel.Content = wikiPage.Namespace.Markup.Convert(revisions.First().Content);
                    }
                    else
                    {
                        var revisionCreated = new DateTime(int.Parse(revision.Substring(0, 4)), int.Parse(revision.Substring(4, 2)), int.Parse(revision.Substring(6, 2)), int.Parse(revision.Substring(8, 2)), int.Parse(revision.Substring(10, 2)), int.Parse(revision.Substring(12, 2)), DateTimeKind.Utc);
                        wikiPageViewModel.Revision = revisions.Single(x => x.Created == revisionCreated).Created.ToString("u");
                        wikiPageViewModel.Content = wikiPage.Namespace.Markup.Convert(revisions.Single(x => x.Created == revisionCreated).Content);
                    }
                }

                return View(wikiPageViewModel);
            }
            catch (MvcWiki.Exceptions.NamespaceDoesNotExistException)
            {
                return View("PageDoesNotExist", wikiPageViewModel);
            }
            catch (MvcWiki.Exceptions.PageDoesNotExistException)
            {
                return View("PageDoesNotExist", wikiPageViewModel);
            }
        }

        public ActionResult Revisions(string @namespace, string page)
        {
            var wikiPageViewModel = new MvcWiki.ViewModel.WikiPageViewModel
            {
                Namespace = @namespace,
                Name = page
            };

            try
            {
                var wikiPage = WikiPageService.GetWikiPage(@namespace, page);

                if (wikiPage.Revisions.Count > 0)
                {
                    wikiPageViewModel.HasContent = true;

                    var revisions = wikiPage.Revisions.OrderByDescending(x => x.Created).ToList();

                    wikiPageViewModel.Revisions = revisions.ToDictionary(x => x.Created.ToString("u"), x => x.Created.ToString("yyyyMMddHHmmss"));
                }

                return View(wikiPageViewModel);
            }
            catch (MvcWiki.Exceptions.NamespaceDoesNotExistException)
            {
                return View("PageDoesNotExist", wikiPageViewModel);
            }
            catch (MvcWiki.Exceptions.PageDoesNotExistException)
            {
                return View("PageDoesNotExist", wikiPageViewModel);
            }
        }

        public ActionResult Create(string @namespace)
        {
            var wikiPageViewModel = new MvcWiki.ViewModel.WikiPageViewModel
            {
                Namespace = @namespace,
            };

            return View(wikiPageViewModel);
        }

        [HttpPost]
        public ActionResult Create(WikiPageViewModel wikiPageViewModel)
        {
            MvcWiki.Model.WikiNamespace wikiNamespace = null;

            try
            {
                wikiNamespace = WikiNamespaceService.GetWikiNamespace(wikiPageViewModel.Namespace);
            }
            catch (MvcWiki.Exceptions.NamespaceDoesNotExistException)
            {
                wikiNamespace = new MvcWiki.Model.WikiNamespace
                {
                    Name = wikiPageViewModel.Namespace,
                    Markup = new MvcWiki.Web.Prototype.MVC2P1.Wiki.Prototyping.WikiMarkupMarkdown { Name = "Markdown" }
                };
            }

            WikiPageService.CreateWikiPage(wikiNamespace, wikiPageViewModel.Name);

            return RedirectToAction("show", new { @namespace = wikiPageViewModel.Namespace, page = wikiPageViewModel.Name });
        }

        public ActionResult Edit(string @namespace, string page)
        {
            var wikiPageViewModel = new MvcWiki.ViewModel.WikiPageViewModel
            {
                Namespace = @namespace,
                Name = page
            };

            try
            {
                var wikiPage = WikiPageService.GetWikiPage(@namespace, page);

                if (wikiPage.Revisions.Count() > 0)
                {
                    wikiPageViewModel.HasContent = true;

                    var revisions = wikiPage.Revisions.OrderByDescending(x => x.Created).ToList();

                    wikiPageViewModel.Revisions = revisions.ToDictionary(x => x.Created.ToString("u"), x => x.Created.ToString("yyyyMMddHHmmss"));

                    wikiPageViewModel.Revision = revisions.First().Created.ToString("u");

                    wikiPageViewModel.Content = revisions.First().Content;
                }
            }
            catch (MvcWiki.Exceptions.NamespaceDoesNotExistException)
            {
                return View("PageDoesNotExist", wikiPageViewModel);
            }
            catch (MvcWiki.Exceptions.PageDoesNotExistException)
            {
                return View("PageDoesNotExist", wikiPageViewModel);
            }

            return View(wikiPageViewModel);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(WikiPageViewModel wikiPageViewModel)
        {
            try
            {
                var wikiPage = WikiPageService.GetWikiPage(wikiPageViewModel.Namespace, wikiPageViewModel.Name);
                var wikiPageRevision = new MvcWiki.Model.WikiPageRevision(DateTime.Now.ToUniversalTime(), wikiPageViewModel.Content);
                wikiPage.Revisions.Add(wikiPageRevision);
                WikiPageService.SaveWikiPage(wikiPage);
            }
            catch (MvcWiki.Exceptions.NamespaceDoesNotExistException)
            {
                return View("PageDoesNotExist", wikiPageViewModel);
            }
            catch (MvcWiki.Exceptions.PageDoesNotExistException)
            {
                return View("PageDoesNotExist", wikiPageViewModel);
            }
            catch
            {
                return View();
            }

            return RedirectToAction("show", new { @namespace = wikiPageViewModel.Namespace, page = wikiPageViewModel.Name });
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Rollback(WikiPageViewModel wikiPageViewModel)
        {
            try
            {
                var wikiPage = WikiPageService.GetWikiPage(wikiPageViewModel.Namespace, wikiPageViewModel.Name);

                if (wikiPage.Revisions.Count > 0)
                {
                    if (!String.IsNullOrEmpty(wikiPageViewModel.Revision))
                    {
                        var wikiPageRevisionCreated = new DateTime(int.Parse(wikiPageViewModel.Revision.Substring(0, 4)), int.Parse(wikiPageViewModel.Revision.Substring(4, 2)), int.Parse(wikiPageViewModel.Revision.Substring(6, 2)), int.Parse(wikiPageViewModel.Revision.Substring(8, 2)), int.Parse(wikiPageViewModel.Revision.Substring(10, 2)), int.Parse(wikiPageViewModel.Revision.Substring(12, 2)), DateTimeKind.Utc);

                        var wikiPageRevision = wikiPage.Revisions.Single(x => x.Created == wikiPageRevisionCreated);

                        var newWikiPageRevision = new MvcWiki.Model.WikiPageRevision(DateTime.Now.ToUniversalTime(), wikiPageRevision.Content);

                        wikiPage.Revisions.Add(newWikiPageRevision);
                        WikiPageService.SaveWikiPage(wikiPage);
                    }
                }
            }
            catch (MvcWiki.Exceptions.NamespaceDoesNotExistException)
            {
                return View("PageDoesNotExist", wikiPageViewModel);
            }
            catch (MvcWiki.Exceptions.PageDoesNotExistException)
            {
                return View("PageDoesNotExist", wikiPageViewModel);
            }

            return RedirectToAction("show", new { @namespace = wikiPageViewModel.Namespace, page = wikiPageViewModel.Name });
        }

        public ActionResult Delete(string @namespace, string page)
        {
            var wikiPageViewModel = new MvcWiki.ViewModel.WikiPageViewModel
            {
                Namespace = @namespace,
                Name = page
            };

            try
            {
                WikiPageService.GetWikiPage(@namespace, page);
            }
            catch (MvcWiki.Exceptions.NamespaceDoesNotExistException)
            {
                return View("PageDoesNotExist", wikiPageViewModel);
            }
            catch (MvcWiki.Exceptions.PageDoesNotExistException)
            {
                return View("PageDoesNotExist", wikiPageViewModel);
            }

            return View(wikiPageViewModel);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Delete(WikiPageViewModel wikiPageViewModel)
        {
            WikiPageService.DeleteWikiPage(wikiPageViewModel.Namespace, wikiPageViewModel.Name);

            return RedirectToAction("show", new { @namespace = wikiPageViewModel.Namespace, page = wikiPageViewModel.Name });
        }
    }
}
